#include <QUndoStack>

#include "PointRuledSurfaceHandler.h"
#include "Qt3DPicker.h"

#include "CmdManager.h"
#include "Scene.h"
#include "SendPointHandlerBase.h"
#include "SelectHandler3D.h"
#include "Operation/OpAdd.h"
#include "LineStrip3D.h"
#include "Arc3D.h"
#include "Spline3D.h"
#include "Surface.h"
#include "PointHandler.h"
#include "OsgUtil.h"

PointRuledSurfaceHandler::PointRuledSurfaceHandler()
{
}

PointRuledSurfaceHandler::~PointRuledSurfaceHandler()
{
}

void PointRuledSurfaceHandler::input(const QVariant& data, const QString& rawInput, CommandSource cs)
{
	auto scene = getScene();
	auto sph = getSendPointHandler();
	auto selector = qobject_cast<SelectHandler3D*>(getSelectHandler());
	if (data.type() == QVariant::Bool)
	{
		bool esc = !data.toBool();
		if (esc)
		{
			selector->clearSelection();
			clearInput();
			if (m_curve1)
			{
				m_curve1->setSelected(false);
			}
			emit finished();
			return;
		}
	}

	if (status() == 0)
	{
		selector->beginSelect(D3CurveMask, 1);
		prompt(1, tr("选择三维曲线: "));
		return;
	}

	if (status() == 1)
	{
		if (selector->done())
		{
			std::set<std::shared_ptr<INode>> nodes = selector->selectionSet();
			if (nodes.empty())
			{
				emit finished();
				return;
			}
			std::shared_ptr<INode> node = *nodes.begin();
			auto curve1 = std::dynamic_pointer_cast<Ent>(node);
			if (curve1)
			{
				m_curve1 = curve1;
				selector->clearSelection();
				m_curve1->setSelected(true);
				enableMouseHandler(MouseHandlerID::PointSender);
				m_pointStateMachine = std::make_shared<PointHandler>();
				m_pointStateMachine->setCmdManager(cmdManager());
				m_pointStateMachine->setPrompt0(tr("指定点"));
				m_pointStateMachine->input(data, rawInput, cs);
				if (sph)
				{
					sph->setPointMask(CS_LBTNDOWN);
				}
				setStatus(2);
			}
		}
		return;
	}

	if (status() == 2)
	{
		m_pointStateMachine->input(data, rawInput, cs);
		if (m_pointStateMachine->done())
		{
			m_point = m_pointStateMachine->getPoint();
			auto line = std::dynamic_pointer_cast<LineStrip3D>(m_curve1);
			if (line)
			{
				auto points = line->getPoints();
				auto lineVec = points[0] - points[1];
				lineVec.normalize();
				auto pointStartVec = points[0] - m_point;
				pointStartVec.normalize();
				if (pointApprox(lineVec,pointStartVec) || pointApprox(lineVec, -pointStartVec) || pointApprox(pointStartVec,osg::Vec3d(0,0,0)))
				{
					remark(tr("创建直纹曲面失败"));
					emit finished();
					return;
				}
			}
			auto surface = makeRuledSurface(false);
			if (surface)
			{
				auto undoStack = scene->undoStack();
				std::set<std::shared_ptr<INode>> children;
				children.insert(surface);
				undoStack->push(new OpAdd(children));
			}
			else
			{
				remark(tr("创建直纹曲面失败"));
			}
			selector->clearSelection();
			m_curve1->setSelected(false);
			emit finished();
		}
		return;
	}
}
